package javaproject;

import com.sun.j3d.utils.geometry.Primitive;
import javax.media.j3d.Appearance;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Vector3d;

abstract public class MyPrimitive extends Primitive{
    public double x,y,z;
    public double radX,radY,radZ;   //角度範圍[0, 2*PI)
    protected Shape3D shape;
    protected Transform3D translate;
    protected TransformGroup transG;
    protected Appearance app;

    protected Transform3D T;	//只存旋轉
    protected Transform3D Tx;
    protected Transform3D Ty;
    protected Transform3D Tz;

    protected Transform3D scaleAndRot;

    public MyPrimitive(double x, double y, double z, Appearance app)
    {
	this.radX = 0;
	this.radY = 0;
	this.radZ = 0;
        this.x = x;
        this.y = y;
        this.z = z;
        this.app = app;
        transG = new TransformGroup();
        translate = new Transform3D();
	T = new Transform3D();
	Tx = new Transform3D();
	Ty = new Transform3D();
	Tz = new Transform3D();
	scaleAndRot = new Transform3D();
        transG.addChild(this);
	moveTo(x,y,z);
    }
    public TransformGroup getTransformGroup(){
        return transG;
    }
    public void moveTo(double[] pos)
    {
        moveTo(pos[0], pos[1], pos[2]);
    }
    public void moveTo(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
        translate.set(new Vector3d(x,y,z));
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void move(double x, double y, double z)
    {
        this.x += x;
        this.y += y;
        this.z += z;
        translate.set(new Vector3d(this.x,this.y,this.z));
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);

    }
    public void rotX(double x)
    {
        if(x+radX >= Math.PI*2)
            radX = x+radX - Math.PI*2;
        else if(x+radX < 0)
            radX = x+radX + Math.PI*2;
        else
            radX += x;
	T.rotX(x);
        Tx.mul(T);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void rotY(double y)
    {
        if(y+radY >= Math.PI*2)
            radY = y+radY - Math.PI*2;
        else if(y+radY < 0)
            radY = y+radY + Math.PI*2;
        else
            radY += y;
	T.rotY(y);
        Ty.mul(T);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void rotZ(double z)
    {
        if(z+radZ >= Math.PI*2)
            radZ = z+radZ - Math.PI*2;
        else if(z+radZ < 0)
            radZ = z+radZ + Math.PI*2;
        else
            radZ += z;
	T.rotZ(z);
        Tz.mul(T);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void rotXto(double x)
    {
        if(x >= Math.PI*2)
            radX = x - Math.PI*2;
        else if(x < 0)
            radX = x + Math.PI*2;
        else
            radX = x;
        Tx.rotX(radX);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void rotYto(double y)
    {
        if(y >= Math.PI*2)
            radY = y - Math.PI*2;
        else if(y < 0)
            radY = y + Math.PI*2;
        else
            radY = y;
        Ty.rotY(radY);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void rotZto(double z)
    {
        if(z >= Math.PI*2)
            radZ = z - Math.PI*2;
        else if(z < 0)
            radZ = z + Math.PI*2;
        else
            radZ = z;
        Tz.rotZ(radZ);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }
    public void rotTo(double x, double y, double z)
    {
        if(x >= Math.PI*2)
            radX = x - Math.PI*2;
        else if(x < 0)
            radX = x + Math.PI*2;
        else
            radX = x;
        if(y >= Math.PI*2)
            radY = y - Math.PI*2;
        else if(y < 0)
            radY = y + Math.PI*2;
        else
            radY = y;
	if(z >= Math.PI*2)
            radZ = z - Math.PI*2;
        else if(z < 0)
            radZ = z + Math.PI*2;
        else
            radZ = z;

	Tx.rotX(radX);
	Ty.rotY(radY);
        Tz.rotZ(radZ);
        T.set(Tx);
        T.mul(Ty);
        T.mul(Tz);
	scaleAndRot.set(translate);
	scaleAndRot.mul(T);
        transG.setTransform(scaleAndRot);
    }

    @Override
    public Shape3D getShape(int i) {
        return shape;
    }

    @Override
    public Appearance getAppearance(int i) {
        return app;
    }

    @Override
    public Appearance getAppearance() {
        return app;
    }
    @Override
    public void setAppearance(Appearance aprnc) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}